package com.zjw.socket.demo.starter.messageService.service;


import com.zjw.socket.demo.starter.annotation.core.Bean;
import com.zjw.socket.demo.starter.annotation.core.Inject;
import com.zjw.socket.demo.starter.messageService.*;
import com.zjw.socket.demo.starter.plugin.impl.aop.Aspect;

import java.util.List;

@Bean(name = "MessageTransferService")
public class MessageTransferService {

  private final Message STUB_MESSAGE = MessageCacheFactory.obtain();

  @Inject(query = "MemoryMessageDataBase")
  public IMessageDataBase messageDataBase;

  @Inject(query = "SimpleUserPool")
  public IUserPool userPool;

  @Inject(query = "SimpleUserDataBase")
  public IUserDataBase userDataBase;

  //for cglib
  public MessageTransferService() {
    STUB_MESSAGE.setFromId(0);
    STUB_MESSAGE.setType(SystemMessageType.INVALID_TO_ID);
  }

  @Aspect(around = "com.zjw.socket.demo.starter.template.utils.AopUtils#runtimeMillis")
  public void transferTo(Message message) {
    long toId = message.getToId();
    long fromId = message.getFromId();
    int processStrategy = message.getProcessStrategy();
    int type = message.getType();

    //无效toId，直接返回通知
    if (!invalidUserId(toId)) {
      STUB_MESSAGE.setType(SystemMessageType.INVALID_TO_ID);
      STUB_MESSAGE.setToId(fromId);
      //源消息返回
      STUB_MESSAGE.setBytes(MessageParser.toByte(message));
      IConnectSession connectSession = userPool.getConnectSession(fromId);
      connectSession.writeMessage(STUB_MESSAGE);
      return;
    }

    //id有效，但处理策略需friend id，返回
    if (!isFriend(fromId, toId) && MessageProcessStrategy.hasFlag(processStrategy, MessageProcessStrategy.TO_ID_IS_FRIEND_SEND_MASK)) {
      STUB_MESSAGE.setType(SystemMessageType.NOT_FRIEND_TO_ID);
      STUB_MESSAGE.setToId(fromId);
      IConnectSession connectSession = userPool.getConnectSession(fromId);
      connectSession.writeMessage(STUB_MESSAGE);
      return;
    }


    IConnectSession connectSession = userPool.getConnectSession(toId);

    if (connectSession == null) {
      if (MessageProcessStrategy.hasFlag(processStrategy, MessageProcessStrategy.OFFLINE_TO_ID_CACHE_MASK)) {
        if (MessageProcessStrategy.hasFlag(processStrategy, MessageProcessStrategy.KEEP_MESSAGE_TYPE_LATEST_MASK)) {
          //移除from-to id 对应的 此类型的type消息
          messageDataBase.removeMessageBy(toId, fromId, type);
        }
        messageDataBase.insertMessageList(message);
      }
    } else {
      connectSession.writeMessage(message);
    }
  }


  private boolean isFriend(long userId, long otherId) {
    User user = userDataBase.queryUserByUsername(userId);
    User other = userDataBase.queryUserByUsername(otherId);
    if (user == null || other == null) {
      return false;
    }

    List<UserFriend> friends = user.friends;
    for (UserFriend friend : friends) {
      if (friend.username == other.username) {
        return true;
      }
    }
    return false;
  }

  private boolean invalidUserId(long toId) {
    return userDataBase.queryUserByUsername(toId) != null;
  }

  @Aspect(around = "com.zjw.socket.demo.starter.template.utils.AopUtils#runtimeMillis")
  public void requestMessageList(long userId) {
    List<Message> messages = messageDataBase.getMessageList(userId);
    if (messages != null) {
      IConnectSession connectSession = userPool.getConnectSession(userId);
      messages.forEach(connectSession::writeMessage);
    }
  }
}
